package juc.work;

import java.util.ArrayDeque;
import java.util.Deque;

/**
 * 生产者 消费者模型
 */
class Storage {
    private static int MAX_CAPACITY = 100;
    private Deque<Integer> queue = new ArrayDeque<>();

    // num 为生产者生产数量
    public void produce(int num) {
        synchronized (queue) {
            while(queue.size() + num > MAX_CAPACITY) {
                System.out.println("容量不足，无法生产");
                try {
                    queue.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }

            for(int i = 0; i < num; i++) {
                queue.add((int) Math.random());
            }
            System.out.println  ("已生产" + num + " 队列容量" + queue.size());
            queue.notifyAll();
        }
    }

    public void consume(int num) {
        synchronized (queue) {
            while(queue.size() < num) {
                System.out.println("容量不足，无法消费");
                try {
                    queue.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            for(int i = 0; i < num; i++) {
                queue.poll();
            }
            System.out.println("已消费" + num + " 队列容量" + queue.size());
            queue.notifyAll();
        }
    }
}

class Producer extends Thread {
    private int num;
    private Storage storage;
    public Producer(Storage storage) {
        this.storage = storage;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public void run() {
        storage.produce(this.num);
    }
}

class Consumer extends Thread {
    private int num;
    private Storage storage;
    public Consumer(Storage storage) {
        this.storage = storage;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public void run() {
        storage.consume(this.num);
    }
}



public class TestConProModel {
    public static void main(String[] args) {
        Storage storage = new Storage();
        Producer producer1 = new Producer(storage);
        Producer producer2 = new Producer(storage);
        Producer producer3 = new Producer(storage);
        Producer producer4 = new Producer(storage);
        Consumer consumer1 = new Consumer(storage);
        Consumer consumer2 = new Consumer(storage);
        Consumer consumer3 = new Consumer(storage);
        producer1.setNum(10);
        producer2.setNum(20);
        consumer1.setNum(10);
        consumer2.setNum(30);
        producer3.setNum(30);
        producer4.setNum(50);
        consumer3.setNum(50);
        consumer1.start();
        consumer2.start();
        consumer3.start();
        producer1.start();
        producer2.start();
        producer3.start();
        producer4.start();
    }
}
